Skip to content

One Way Platforms and Bouncy Platforms - #2

Open
Lonkman0403 wants to merge 12 commits into
bearlikelion:mainfrom
Lonkman0403:lonk-dev
Open

One Way Platforms and Bouncy Platforms#2
Lonkman0403 wants to merge 12 commits into
bearlikelion:mainfrom
Lonkman0403:lonk-dev

Conversation

@Lonkman0403

@Lonkman0403 Lonkman0403 commented Jan 2, 2026

Copy link
Copy Markdown
Contributor

So, i first messed with the sprite sheet and tileset. I added a bunch new platforms that we can use on other maps, and then put all the skinny platforms onto a unique physics layer.

The player detects the one way platform below itself, and then adds the one way platform layer to the player's collision mask if its not pressing down and the player is at rest or moving down.

I know this works because this is how i make it work for Bonk-a-Donk.

Caveats to this approach:

  • If the platform is too thick, pressing down has to take longer before fully falling through.
  • If the platform is too thin, the platform wont be detected at all. Also, if falling too fast onto the platform and the platform is too thin, the platform is not detected between frames of movement.
  • The platforms desired thickness depends on the player shape's distance to the player's one-way shape (gap must be a little smaller than the platform so at rest the platform is barely detected)

But, as long as all one-way platforms maintain identical thickness and the one-way check area on the player is not modified, this mechanic should function exactly as intended.

I also added Bouncy Platforms which function on a separate collision layer.
I did this by replacing move_and_slide() in _physics_process() (player.gs) with an _apply_physics() function that handles collision math and applying the physics to the player. it calls move_and_slide(), checks the resulting collision, checks if its a bouncy layer (layer 3), does collision math,calls move_and_slide() again, and then corrects final positions that got modified by the move_and_slide() so you cannot gain height with successive bounces

I cut up some of the art and made some one-way platform lookin things out of the existing art (not complete)
I did this by detecting when the one way platform should be in the player's collision mask, and put the one way platforms on layer 2 (also i named the layers and added a const for the oneway platform layer number to avoid magic numbers in player.gd)
cuz it was causing side-falling issues. you shouldnt bump into them like that
didnt think about the tabs
drew a special_tiles png for bouncy platforms and other things in the future that have special properties. added bouncy collision math in the player for collisions against collision layer 3.
@Lonkman0403 Lonkman0403 changed the title One Way Platforms One Way Platforms and Bouncy Platforms Jan 4, 2026

@bearlikelion bearlikelion left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey Lonk!

I really appreciate you taking the time to improve the gameplay of this by adding in one-way and bouncy platforms. But, this is meant to be a tutorial focused project. Improving the gameplay helps improve the fun of the game, but is also kind of out of the scope for what I intended. Again, thank you, this change is awesome.

I apologize for taking so long to review this PR, it was a tough one. I really didn't like the double move_and_slide() which we discussed over Discord and I took some time to implement a cleaner soltution.

My fix is to implement a boolean flag has_pending_bounce that it flipped when colliding with a bounce platform.
Then on the next physics frame we do not apply gravity if this boolean is true which lets the player bounce as expected.

	# Apply pending bounce from last frame FIRST
	if has_pending_bounce:		
		velocity = pending_bounce_velocity
		has_pending_bounce = false
	elif not is_on_floor():
		# Apply normal gravity
		velocity.y = min(velocity.y + get_gravity().y * gravity_scale * delta, max_fall_speed)

This change also removes the need for the _bouncy_position_correction function.
There's some small formatting and nitpicks in the review I'd like you to address before a merge.

I'd like you to try to implement the has_pending_bounce flag yourself, but if you're running into trouble here's my solution: https://gist.github.com/bearlikelion/ad6f7f1e69253dc36687832c16fe8c0c

Thanks,
Mark

Comment thread Scenes/Player/player.gd
if !col: return

# If it detects a bouncy thing, bounce.
if !(PhysicsServer2D.body_get_collision_layer(col.get_collider_rid()) & BOUNCY_LAYER):

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: I prefer using not to !, they do the same thing but being verbose makes it easier for me to understand and read at a glance.

I frequently still use ! though so not a major change

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also a double negative? I'm not sure we need this here because then it's checking collision layer on every collision, not just bouncy collisions.

Comment thread Scenes/Player/player.gd
move_and_slide()
_bouncy_position_correction(pos1, pos2, col.get_normal())

_on_landed()

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential Bug: I think this should be wrapped in an is_on_floor() to prevent the function accidentally firing before the player collides with the platform.

Comment thread Scenes/Player/player.gd
if !(PhysicsServer2D.body_get_collision_layer(col.get_collider_rid()) & BOUNCY_LAYER):
var new_vel: Vector2 = _bouncy_col_math(vel, col.get_normal())
velocity = new_vel
move_and_slide()

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this double move_and_slide() solution and will provide my solution in the PR review comment.

Comment thread Scenes/Player/player.gd
extends CharacterBody2D

enum {
NULL,

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like NULL being in an ENUM. NULL = Nothing, an ENUM defines something.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bouncy layer is set to 4 in your bitwise math.

My solution was to implement

enum {
	NULL = 0,
	DEFAULT_LAYER = 1,
	ONE_WAY_LAYER = 2,
	BOUNCY_LAYER = 4
}

Comment thread Scenes/Player/player.gd
_on_landed()
was_on_floor = is_on_floor()

#Handle one-way platforms

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Space after # for readability

Comment thread Scenes/Player/player.gd

# Handles the one-way platform functionality.
func _handle_one_way() -> void:
# The only time that a one way platform should have collision is when: its detected by the check, the player is moving downwards or resting, and the down direction is not pressed.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is way too long, there's guide lines in the Godot editor for soft / hard limit.

Image

if you go past the first line it's okay, if you reach the second line you need to line break for readability.

@bearlikelion bearlikelion added enhancement New feature or request awaiting update Waiting for the contributor to complete a review labels Jan 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting update Waiting for the contributor to complete a review enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants